<script setup lang="ts">
import { customTranslate } from "./tool/customTranslate";
import "bpmn-js/dist/assets/diagram-js.css";
import "bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css";
import Task from "./node/index.vue";
import Modeler from "bpmn-js/lib/Modeler";
import { ref } from "vue";
import { NodeInfo } from "./node/FlowableType";
import { ProcessDefineVO } from "@/api/flowable";

const bpmnModeler = ref<Modeler>();

const task = ref();

const nodeMap = ref<Map<string, NodeInfo>>(new Map());

const processDefine = ref<ProcessDefineVO>();

const businessFieldList = ref<Array<any>>();

const createBpmnModeler = () => {
  bpmnModeler.value = new Modeler({
    container: "#container",
    additionalModules: [{ translate: ["value", customTranslate] }]
  });
  // 节点选中事件
  bpmnModeler.value.on("selection.changed", eventSelectionHandle);
  // 节点变更事件
  bpmnModeler.value.on("element.changed", eventElementHandle);
};

const eventElementHandle = (e: any) => {
  const { element } = e;
  if (element.businessObject.name) {
    const node = nodeMap.value.get(element.id);
    if (node && node.name != element.businessObject.name) {
      node.name = element.businessObject.name;
    }
  }
};

const eventSelectionHandle = (e: any) => {
  const element = e.newSelection[0] || null;
  if (element && element.type != "bpmn:TextAnnotation") {
    const nodeInfo: NodeInfo = getNodeInfo(element.id, element.type);
    updateNode(element.id);
    task.value.init(nodeInfo);
  } else {
    task.value.init();
  }
};

const updateNode = (id: string) => {
  const modeling: { updateProperties: Function } | undefined =
    bpmnModeler.value?.get("modeling");
  const elementRegistry: { get: Function } | undefined =
    bpmnModeler.value?.get("elementRegistry");
  const nodeInfo: NodeInfo | undefined = nodeMap.value.get(id);
  if (modeling && elementRegistry && nodeInfo) {
    const element = elementRegistry.get(id);
    modeling.updateProperties(element, { name: nodeInfo.name });
  }
};

const getNodeInfo = (nodeId: string, type: string): NodeInfo => {
  const nodeInfo: NodeInfo | undefined = nodeMap.value.get(nodeId);
  if (nodeInfo) {
    nodeInfo.nodeType = type;
    return nodeInfo;
  } else {
    const nodeInfo = {
      id: nodeId,
      name: "",
      nodeType: type
    };
    nodeMap.value.set(nodeId, nodeInfo);
    return nodeInfo;
  }
};

const downloadXml = () => {
  bpmnModeler.value?.saveXML().then(res => {
    console.log(res.xml);
  });
};

const downloadSvg = () => {
  bpmnModeler.value?.saveSVG().then(res => {
    console.log(res.svg);
  });
};

const importXml = (xml: string) => {
  bpmnModeler.value?.importXML(xml);
  bpmnModeler.value?.createDiagram();
};

const initBpmn = (processDefineVO: ProcessDefineVO) => {
  processDefine.value = processDefineVO;
  getBusinessFields(processDefine.value.businessApi);
  createBpmnModeler();
  if (processDefineVO.bpmn) {
    importXml(processDefineVO.bpmn);
  } else {
    bpmnModeler.value?.createDiagram();
  }
};

const getBusinessFields = (businessApi: string) => {
  console.log(businessApi);
  businessFieldList.value = [
    {
      columnApi: "名称",
      columnName: "name",
      dataType: "String"
    }
  ];
};

const saveNode = () => {
  console.log(nodeMap);
};

defineExpose({
  initBpmn
});
</script>

<template>
  <el-card class="main-flowable">
    <el-row>
      <div style="float: left; margin-left: 20px">
        <el-button @click="downloadXml">下载xml</el-button>
        <el-button @click="downloadSvg">下载svg</el-button>
        <el-button @click="importXml('')">导入xml</el-button>
        <el-button @click="saveNode">保存流程</el-button>
      </div>
    </el-row>
    <el-row>
      <el-col :span="18">
        <div
          id="container"
          class="container"
          style="width: 100%; height: 900px"
        />
      </el-col>
      <el-col :span="6">
        <el-card class="box-card" style="height: 100%">
          <template #header>
            <div>
              <span>属性盘</span>
            </div>
          </template>
          <div>
            <Task
              ref="task"
              :processDefine="processDefine"
              :updateNode="updateNode"
            />
          </div>
        </el-card>
      </el-col>
    </el-row>
  </el-card>
</template>

<style>
.main-flowable {
  -webkit-box-flex: 1;
  -ms-flex: 1;
  flex: 1;
  height: 100%;
  position: relative;
  background: url("")
    repeat !important;
}
</style>
